package com.ming_za.odupdaterserver.core.utils.account.impl;

import com.ming_za.odupdaterserver.core.utils.account.api.TokenClaims;
import com.ming_za.odupdaterserver.core.utils.account.api.TokenFactory;
import com.ming_za.odupdaterserver.core.utils.account.token.TokenData;
import com.ming_za.odupdaterserver.core.utils.account.token.TokenPackage;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;

import java.security.SecureRandom;
import java.util.Date;

/**
 * 基于JWT实现的token工厂实现类
 */
public class JWTTokenFactory implements TokenFactory {

    /**
     * Claims接口，动态设置Claims，可为null
     */
    private final TokenClaims tokenClaims;

    /**
     * 签发者
     */
    private final String issuer;

    public JWTTokenFactory(TokenClaims tokenClaims, String issuer) {
        this.tokenClaims = tokenClaims;
        this.issuer = issuer;
    }

    @Override
    public TokenPackage createToken(TokenData tokenData, long tokenExpire){

        byte[] key = Jwts.SIG.HS256.key().random(new SecureRandom()).build().getEncoded();

        String token = Jwts.builder()
                .signWith(Keys.hmacShaKeyFor(key))
                .claims(tokenClaims != null ? tokenClaims.getClaims(tokenData.getAccount()) : null)
                .issuer(issuer)
                .subject(String.valueOf(tokenData.getAccount()))
                .issuedAt(new Date(System.currentTimeMillis()))
                .expiration(new Date(System.currentTimeMillis() + tokenExpire))
                .compact();

        return new TokenPackage(token,key);

    }

    @Override
    public TokenData decodeToken(long account,String token, byte[] key, long tokenExpire) {
        try {
            Claims payload = Jwts.parser().verifyWith(Keys.hmacShaKeyFor(key))
                    .build()
                    .parseSignedClaims(token)
                    .getPayload();

            if(!payload.getIssuer().equals(issuer) || !String.valueOf(account).equals(payload.getSubject())){
                return null;
            }

            long createTime = payload.getIssuedAt().getTime();

            return new TokenData(account,createTime);
        }catch (Exception e){
            return null;
        }
    }
}
